package controller;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.InputMismatchException;
import java.util.Scanner;

import business.Accounts;
import business.Schedule;
import data.Job;
import data.LMA;
import data.Scheduler;
import data.Volunteer;

/**
 * The WTAAction is the controller class that controls and reads user
 * input.
 * 
 * @author Krisnil Gounder.
 * @version March 5th, 2011.
 * 
 */
public class WTAAction {
	/**
	 * Boolean condition checks if the program should run or not.
	 */
	private boolean runProgram = true;
	/**
	 * Checks user input for the option that has been selected.
	 */
	private int userNumber;
	/**
	 * New Accounts.
	 */
	public Accounts accounts = new Accounts();
	/**
	 * New Schedule.
	 */
	public Schedule schedule = new Schedule();
	/**
	 * Read in scanner input from the user.
	 */
	private Scanner in = new Scanner(System.in);
	/**
	 * Confirmation flag set up the user.
	 */
	private char confirmation = 0;
	/**
	 * File to write to.
	 */
	private File writeFile;
	/**
	 * Writer output.
	 */
	private Writer output = null;
	/**
	 * Current User.
	 */
	private Volunteer currentUser;
	/**
	 * File to read and write to.
	 */
	private String fileName;
	/**
	 * osName.
	 */
	private String osName;
	
	/**
	 * WTAAction Constructor.
	 * 
	 * @param fileName the file that will load and store systems data.
	 * 
	 */
	public WTAAction(String fileName) {
		runProgram = true;
		userNumber = 0;
		accounts = new Accounts();
		schedule = new Schedule();
		in = new Scanner(System.in);
		confirmation = 0;
		currentUser = null;
		osName = System.getProperty("os.name");
		this.fileName = fileName;
	}

	/**
	 * The main that calls on respective methods for execution.
	 * 
	 * @throws IOException, if the file not loaded correctly.
	 * 
	 */
	public void run() throws IOException {
		loadFile();
		System.out
				.println("  				\\\\      //\\\\      //       ===========       //\\\\");
		System.out
				.println("  				 \\\\    //  \\\\    //  		||     	    //  \\\\");
		System.out
				.println("  		 		  \\\\  //    \\\\  //  		||    	   //====\\\\");
		System.out
				.println("   		  		   \\\\//      \\\\//  		||   	  //   	  \\\\");
		System.out.println();
		System.out
				.println("Welcome to the Washington Trail Maintainance Agency");
		System.out.println();

		do {
			if (runProgram) {
				mainMenu();
			}
			if (userNumber == 0) {
				saveFile();
				output.close();
				System.exit(0);
			}
			if (userNumber == 1) {
				unregisteredUser();
			} else if (userNumber > 1) {
				login();
				if (userNumber == 2) {
					volunteer();
				} else if (userNumber == 3) {
					scheduler();
				} else if (userNumber == 4) {
					lma();
				}
			}
			System.out.println();
			System.out.println(" Enter 1 to return to Main Menu");
			System.out.println(" Enter 2 to quit the program");
			userInput();

			if (userNumber == 1) {
				runProgram = true;
			} else {
				System.out.println("Thankyou for using the Washington Trail Agency Program");
				saveFile();
				output.close();
				break;
			}
		} while (true);
	}

	/**
	 * The main menu serves as the home screen from which the user has options
	 * to choose from.
	 * 
	 */
	private void mainMenu() {
		System.out.println(" 0 Exit the System");
		System.out.println(" 1 Unregistered User");
		System.out.println(" 2 Volunteer");
		System.out.println(" 3 Scheduler");
		System.out.println(" 4 Land Management Agency");
		System.out.println();
		System.out
				.print("Please type in the corressponding number to Login as:");
		userInput();
		runProgram = false;
		System.out.println();
	}

	/**
	 * This method validates the integer user input from the console and
	 * verifies that the number selected by the user is within the range or
	 * valid input as specified by the program.
	 * 
	 * @return userNumber, reads the user input and sets the userNumber.
	 * @throws InputMismatchException, if input is invalid.
	 * 
	 */
	public int userInput() {
		try {
			userNumber = in.nextInt();
			if (userNumber < 0 || userNumber > 4) {
				mainMenu();
			}
		} catch (InputMismatchException e) {
			System.out.println("Invalid input!!!");
			System.exit(0);
		}
		return userNumber;
	}

	/**
	 * The following method loads the file with user information.
	 * Originally written by Krisnil and modification done by Faiz.
	 * 
	 * author Krisnil
	 * author Faiz
	 *	  
	 * @throws IOException, if error in loading the file.
	 * 
	 */
	public void loadFile() throws IOException {
		File readFile;
		BufferedReader reader;
		String line = null;
		Scanner token;
		try {
			readFile = new File(fileName);
			reader = new BufferedReader(new FileReader(readFile));
			line = null;
			ArrayList<Volunteer> loadedVolunteers;
			while ((line = reader.readLine()) != null) {
				token = new Scanner(line).useDelimiter(",,");
				if (token.hasNext("LMA")) {
					token.next();
					String organization = token.next();
					String username = token.next();
					String password = token.next();
					String phone = token.next();
					String email = token.next();
					accounts.addAccount(new LMA(organization, username,
							password, phone, email));
				}
				if (token.hasNext("Volunteer")) {
					token.next();
					String name = token.next();
					String surname = token.next();
					String username = token.next();
					String password = token.next();
					String phone = token.next();
					String email = token.next();
					String dob = token.next();
					Boolean isGroupLeader = token.nextBoolean();
					accounts.addAccount(new Volunteer(name, surname, username,
							password, phone, email, dob, isGroupLeader));
				}
				if (token.hasNext("Scheduler")) {
					token.next();
					String username = token.next();
					String password = token.next();
					String phone = token.next();
					String email = token.next();
					accounts.addAccount(new Scheduler(username, password,
							phone, email));
				}
				if (token.hasNext("Job")) {
					token.next();
					String jobName = token.next();
					String lmaPhone = token.next();
					String location = token.next();
					int grade = token.nextInt();
					int difficulty = token.nextInt();
					String description = token.next();
					String date = token.next();
					String time = token.next();
					String lmaName = token.next();
					int size = token.nextInt();
					boolean isVerified = token.nextBoolean();
					boolean hasLeader = token.nextBoolean();
					loadedVolunteers = new ArrayList<Volunteer>();

					while (token.hasNext()) { 
						loadedVolunteers.add((Volunteer)accounts.getAccount(token
								.next()));
					}

					schedule.addJob(new Job(jobName, lmaPhone, location, grade,
							difficulty, description, date, time, lmaName, size,
							isVerified, hasLeader, loadedVolunteers));
				}
			}

		} catch (final IOException e) {
			System.err.println("Unable to read file");
		}
	}

	/**
	 * This method prompts the Unregistered User to fill in the required fields.
	 * 
	 * @throws IOException, if error in creating new volunteer object and passing 
	 * its data.
	 * 
	 */
	private void unregisteredUser() throws IOException {
		System.out.println("> Enter 1 to create a new Volunteer account");
		System.out.println("> Enter 2 to register as a  Land Management Agency");
		System.out.println("> Enter 3 to view list of upcoming trail maintenance jobs.");
		if (userInput() == 1) {
			System.out.print("	Name:");
			String name = in.next();
			System.out.print("	Last Name:");
			String lastName = in.next();
			System.out.print("	Email Address:");
			String emailAddress = in.next();
			System.out.print("	Date of Birth (mm/dd/yyyy):");
			String dob = in.next();
			System.out.print("	Username:");
			String newUsername = in.next();
			System.out.print("	Password:");
			String newPassword = in.next();
			System.out.print("	Phone Number:");
			String newPhone = in.next();
			System.out.print("Is the provided information correct? y/n");
			confirmation = in.next().charAt(0);
			boolean emailVerification = true;

			for (Volunteer theVolunteer : accounts.getVolunteerList()) {
				if (theVolunteer.getEmail().equalsIgnoreCase(emailAddress)) {
					System.out.println("E-mail address is already registered");
					emailVerification = false;
				}
			}
			if (confirmation == 'y' && emailVerification == true) {
				userNumber = 0;
				accounts.addAccount(new Volunteer(name, lastName, newUsername,
						newPassword, newPhone, emailAddress, dob, false));
				System.out.println("New Volunteer Account has been created successfully!");
			}
		} else {
			System.out.println("Currently you may only register as a Volunteer");
		}
	}

	/**
	 * This method requires all registered users to login and verifies the user
	 * types in valid username with corresponding password.
	 * 
	 * @throws IOException
	 *             , if information not found.
	 * 
	 */
	private void login() throws IOException {
		boolean loginVerification = false;
		String username = null;
		try {
			while (loginVerification == false) {
				System.out.print("	Username:");
				username = in.next();
				System.out.print("	Password:");
				String password = in.next();
				System.out.println();
				loginVerification = accounts.verifyPassword(username, password);
			}
			if (userNumber == 2) {
				currentUser = (Volunteer) accounts.getAccount(username);
				volunteer();
			} else if (userNumber == 3) {
				scheduler();
			} else if (userNumber == 4) {
				lma();
			}
		} catch (NullPointerException e) {
			System.out.println("Invalid login information.");
			userNumber = 0;
		}
	}

	/**
	 * This method allows the Volunteer to choose from a list of TMJ's and
	 * confirm his/ her actions.
	 * 
	 */
	private void volunteer() {
		System.out.println("Sign up for Trail Maintenance Job");
		System.out.println();
		int i = 0;
		for (Job theJob : schedule.viewScheduledJob()) {
			System.out.println("		Job Number: " + i++);
			System.out.println(theJob.getInfo() + '\n');
		}
		System.out.print(" > Pick a job number or enter -1 to exit: ");
		int jobNumber = in.nextInt();
		if (jobNumber == -1) {
			userNumber = 1;
		} else {
			System.out.print(" > Request to be a Group Leader? y/n");
			confirmation = in.next().charAt(0);
			if (confirmation == 'y') {
				System.out.println("	Unavilable option from Use Case");
			}
			System.out.print("Confirm your selection? y/n");
			confirmation = in.next().charAt(0);
			if (confirmation == 'y') {
				schedule.viewScheduledJob().get(jobNumber).addVolunteer(currentUser);

				userNumber = 0;
				System.out.println("Signed up for job successfully!");
			}
		}
	}

	/**
	 * This method allows the Scheduler to view list of unscheduled jobs and add
	 * jobs to the schedule respectively.
	 * 
	 */
	private void scheduler() {
		System.out.print("> Enter 1 to view jobs that require scheduling");
		userInput();
		int i = 0;
		if (userNumber == 1) {
			for (Job theJob : schedule.viewUnscheduledJob()) {
				System.out.println("		Job Number: " + i++);
				System.out.println(theJob.getInfo() + '\n');
			}
			System.out.print(" > Pick a job number to schedule:");
			int jobNumber = in.nextInt();
			System.out.print("	Enter date (mm/dd/yyyy): ");
			String date = in.next();
			System.out.print("	Enter time (00:00AM/PM): ");
			String time = in.next();
			schedule.viewUnscheduledJob().get(jobNumber).setDateTime(date, time);
			System.out.println("Job has been updated succesfully");
			System.out.print("Add to trail maintenance schedule? y/n");
			confirmation = in.next().charAt(0);

			if (confirmation == 'y') {
				System.out.println("Confirm? y/n ");
				confirmation = in.next().charAt(0);
				if (confirmation == 'y') {
					Job job = schedule.viewUnscheduledJob().get(jobNumber);
					schedule.removeUnscheduledJob(job);
					job.setVerified(true);
					schedule.addJob(job);
					System.out.println("Information has been updated");
				}
				userNumber = 0;
			}
		}
	}

	/**
	 * The LMA method prompts the LMA to fill in the job request form and send
	 * the request to the Scheduler.
	 * 
	 * @throws IOException, if data passed through is incorrect.
	 * 
	 */
	private void lma() throws IOException {
		String skip = "";
		if (osName.startsWith("Mac")) {
			skip = "\n";
		} if(osName.startsWith("Windows")){
			skip = "\r\n";
		}
		System.out.print("> Enter 1 for a Trail Maintenance Request");
		userInput();
		if (userNumber == 1) {
			System.out.print("	Organization Name:");
			in.skip(skip);
			String lmaName = in.nextLine();
			System.out.print("	Phone Number (XXX-XXX-XXXX):");
			String phoneNumber = in.next();
			System.out.print("	Job Name:");
			in.skip(skip);
			String jobName = in.nextLine();
			System.out.print("	Trail Location:");
			String trailLocation = in.nextLine();
			System.out.print("	Grade %:");
			int grade = in.nextInt();
			System.out.print("	Difficulty (0->low-10->high):");
			int difficulty = in.nextInt();			
			System.out.print("	Description of the job:");
			in.skip(skip);
			String description = in.nextLine();
			System.out.print("	Date (mm/dd/yyyy):");
			String date = in.next();
			System.out.print("	Time (00:00AM/PM): ");
			String time = in.next();
			System.out.print("	Job size:");
			int size = in.nextInt();
			ArrayList<Volunteer> loadedVolunteers = new ArrayList<Volunteer>();
			System.out.print(" Submit? y/n");
			confirmation = in.next().charAt(0);
			if (confirmation == 'y') {
				schedule.addJob(new Job(jobName, phoneNumber, trailLocation, grade,
						difficulty, description, date, time, lmaName, size,
						false, false, loadedVolunteers));
				System.out.println("Request submitted successfully!");
				userNumber = 0;
			}
		}
	}

	/**
	 * This method updates the text file by ensuring that the preloaded data is
	 * preserved and any new data entered by the user is also preserved.
	 * 
	 * @throws IOException, if error in writing to file.
	 * 
	 */
	private void saveFile() throws IOException {
		writeFile = new File(fileName);
		output = new BufferedWriter(new FileWriter(writeFile));

		for (Volunteer theVolunteer : accounts.getVolunteerList()) {
			output.write("Volunteer,," + theVolunteer.toString());
		}
		for (Scheduler theScheduler : accounts.getTheScheduler()) {
			output.write("Scheduler,," + theScheduler.toString());
		}
		for (LMA theLMA : accounts.getLmaList()) {
			output.write("LMA,," + theLMA.toString());
		}
		output.write(schedule.toString());
	}
}
